#include "FITKOrdinaryMeshReaderFASTSIM.h"
#include <QFileInfo>
#include <QDir>
#include <QFile>

#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKSignalTransfer.h"
#include "FITK_Interface/FITKInterfaceMesh/FITKUnstructuredMeshVTK.h"
#include "FITK_Interface/FITKInterfaceModel/FITKElementHex.h"
#include "FITK_Interface/FITKInterfaceModel/FITKElementPolygon.h"
#include "FITK_Interface/FITKInterfaceMesh/FITKUnstructuredFluidMeshVTK.h"
#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"
#include "FITK_Interface/FITKInterfaceModel/FITKElementQuad.h"

#include <QTextCodec>

#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkSTLReader.h>
#include <vtkIdList.h>
#include <vtkCell.h>
#include <vtkCellType.h>
#include <vtkUnstructuredGrid.h>
#include <vtkUnstructuredGridWriter.h>
#include <vtkUnstructuredGridReader.h>
#include <vtkPoints.h>

namespace IO {


    FITKOrdinaryMeshReaderFASTSIM::FITKOrdinaryMeshReaderFASTSIM() = default;

    FITKOrdinaryMeshReaderFASTSIM::~FITKOrdinaryMeshReaderFASTSIM() = default;

    void FITKOrdinaryMeshReaderFASTSIM::run()
    {
        if (_fluidMesh == nullptr || _boundaryManager == nullptr) return;
        read();
    }

    void FITKOrdinaryMeshReaderFASTSIM::consoleMessage(int level, const QString & str)
    {
        //判断消息等级
        switch (level)
        {
        case 1:AppFrame::FITKMessageNormal(str); break;
        case 2: AppFrame::FITKMessageWarning(str); break;
        case 3:AppFrame::FITKMessageError(str); break;
        default: AppFrame::FITKMessageError(str); break;
        }
    }

    void FITKOrdinaryMeshReaderFASTSIM::setDataObject(Core::FITKAbstractDataObject * data)
    {
        auto mesh = dynamic_cast<Interface::FITKUnstructuredMeshVTK*>(data);
        if (mesh == nullptr) return;
        _fluidMesh = new Interface::FITKUnstructuredMeshVTK();
        _boundaryManager = mesh->getBoundaryMeshManager();
    }

    bool FITKOrdinaryMeshReaderFASTSIM::read()
    {
        if (_fluidMesh == nullptr) return false;
        if (_fileName.isEmpty()) return false;

        QString name = _fileName.section('/', -1);
        _fluidMesh->setDataObjectName(name);

        QTextCodec *codec = QTextCodec::codecForName("UTF-8");
        QByteArray ba = codec->fromUnicode(_fileName);
        const char* cFileName = ba.constData();
        // 声明并初始化智能指针
        vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid;
        unstructuredGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();

        // 根据.stl,.vtk后缀选择读取方式
        QFileInfo fileInfo(_fileName);
        if(fileInfo.suffix().compare("vtk", Qt::CaseInsensitive) == 0){
            // 创建 vtkUnstructuredGridReader
            vtkSmartPointer<vtkUnstructuredGridReader> reader = vtkSmartPointer<vtkUnstructuredGridReader>::New();
            reader->SetFileName(cFileName);
            reader->Update();
            unstructuredGrid = reader->GetOutput();
        }else if(fileInfo.suffix().compare("stl", Qt::CaseInsensitive) == 0){
            // 声明并初始化智能指针
            vtkSmartPointer<vtkPolyData> polyData;
            polyData = vtkSmartPointer<vtkPolyData>::New();

            // 创建 vtkSTLReader
            vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
            reader->SetFileName(cFileName);
            reader->Update();
            polyData = reader->GetOutput();

            // 将 vtkPolyData 转换为 vtkUnstructuredGrid
            vtkSmartPointer<vtkPoints> points = polyData->GetPoints();
            vtkSmartPointer<vtkCellArray> polys = polyData->GetPolys();
            unstructuredGrid->SetPoints(points);

            vtkIdType npts;
            vtkIdType const* ptIds;
            polys->InitTraversal();
            // 将三角形面元添加为非结构化网格的单元
            while (polys->GetNextCell(npts, ptIds)) {
                if (npts == 3) {
                    unstructuredGrid->InsertNextCell(VTK_TRIANGLE, npts, ptIds);
                } else {
                    emit FITKAPP->getSignalTransfer()->outputMessageSig(3, tr("Non-triangular face encountered. Skipping."));
                }
            }
        }else{
            emit FITKAPP->getSignalTransfer()->outputMessageSig(3, tr("Please input files of type .stl or .vtk"));
            return false;
        }

        //unstructuredGrid->GetCells();
        _fluidMesh->transformVTKMesh(unstructuredGrid);

        int numPoints = _fluidMesh->getNodeCount();
        int numCells = _fluidMesh->getElementCount();
        if(_fluidMesh == nullptr) {AppFrame::FITKMessageError("VTK READ ERROR");}
        AppFrame::FITKMessageNormal("Grid read successful @Grid Node: "+QString::number(numPoints)+"@Grid CELL: "+QString::number(numCells));
        _fluidMesh->setmodified();
        _boundaryManager->appendDataObj(_fluidMesh);

        return true;
    }

    bool FITKOrdinaryMeshReaderFASTSIM::setupBoundarys()
    {
        if (_boundaryManager == nullptr) return false;

        for (auto boundary : _Boundarys) {
            auto b = new Interface::FITKBoundaryMeshVTK(_fluidMesh);
            //记录边界网格信息 libaojun@20240906
            b->setUserData(Core::FITKUserData::FITKUserRole, boundary->startFace);
            b->setUserData(Core::FITKUserData::FITKUserRole + 1, boundary->nFaces);
            //********************
            for (int i = 0; i < boundary->nFaces; ++i)
            {
                const QList<int>& face = _faces[boundary->startFace + i];
                auto ele = new Interface::FITKElementPolygon;
                ele->setNodeCount(face.size());
                ele->setNodeID(face);
                b->appendElement(ele);
            }
            b->setDataObjectName(boundary->name);
            _boundaryManager->appendDataObj(b);
        }
        return true;
    }

}
